package server;

import game.Card;
import game.Player;
import game.client.Table;
import game.server.ServerTable;

import java.io.Serializable;
import java.util.ArrayList;


import server.utils.CommandType;
import server.utils.Utils;


public class Message implements Serializable {
	private static final long serialVersionUID = 3635384963538773512L;
	/**
	 * To who this message is sent. 
	 * If NULL send to everyone.
	 */
	private String to;
	/**
	 * From who this message came from.
	 */
	private String from;
	/**
	 * Command type.
	 */
	private CommandType type;
	/**
	 * Command's value what that command should do.
	 */
	private String commandValue;
	/**
	 * Date when the message was sent.
	 */
	private String date;
	/**
	 * Card to send.
	 */
	private Card card;
	/**
	 * Currently playing players to send.
	 */
	private ArrayList<Player> players;
	/**
	 * Table.
	 */
	private Table table;
	/**
	 * Construct message object.
	 * @param from who sent message
	 * @param to who needs to recieve that message
	 * @param type command type
	 * @param commandValue command's value 
	 */
	public Message(String from, String to, CommandType type, 
			String commandValue) {
		this.from = from;
		this.to = to;
		this.type = type;
		this.commandValue = commandValue;
		date = Utils.now();
	}
	/**
	 * Construct message object with Table. Sent to everyone.
	 * @param from who sent message
	 * @param type command type
	 * @param table Table to send
	 */
	public Message(String from, CommandType type, Table table) {
		this(from, type, "");
		this.table = table;
	}
	/**
	 * Construct message object with ArrayList<Player>.
	 * @param from who sent message
	 * @param to who needs to recieve that message
	 * @param type command type
	 * @param players players to send
	 */
	public Message(String from, String to, CommandType type,
			ArrayList<Player> players) {
		this(from, to, type, "");
		this.players = players;
	}
	/**
	 * Construct message object with card.
	 * @param from who sent message
	 * @param to who needs to recieve that message
	 * @param type command type
	 * @param card card to send
	 */
	public Message(String from, String to, CommandType type, Card card) {
		this(from, to, type, "");
		this.card = card;
	}
	/**
	 * Construct message object with card. Sended to everyone, except the sender.
	 * @param from who sent message
	 * @param type command type
	 * @param commandValue command's value
	 * @param card card to send
	 */
	public Message(String from, CommandType type, Card card) {
		this(from, type, "");
		this.card = card;
	}
	/**
	 * Construct message object.
	 * Sends message to every client, except himself.
	 * @param from who sent message
	 * @param type command type
	 * @param commandValue command's value
	 */
	public Message(String from, CommandType type, String commandValue) {
		this(from, null, type, commandValue);
	}
	/**
	 * @return the to
	 */
	public synchronized String getTo() {
		return to;
	}
	/**
	 * @return the from
	 */
	public synchronized String getFrom() {
		return from;
	}
	/**
	 * @return the type
	 */
	public synchronized CommandType getType() {
		return type;
	}
	/**
	 * @return the commandValue
	 */
	public synchronized String getCommandValue() {
		return commandValue;
	}
	/**
	 * @return the date
	 */
	public synchronized String getDate() {
		return date;
	}
	
	/**
	 * @return the card
	 */
	public synchronized Card getCard() {
		return card;
	}
	
	/**
	 * @return the players
	 */
	public synchronized ArrayList<Player> getPlayers() {
		return players;
	}
	/**
	 * @return the table
	 */
	public synchronized Table getTable() {
		return table;
	}
	@Override
	public String toString() {
		return date + " - Message [From=\"" + from
				+ "\", to=\"" + to + "\", command=\"" + type +
						"\", value=\"" + commandValue + "\", card=\"" + card +"\"]";
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((commandValue == null) ? 0 : commandValue.hashCode());
		result = prime * result + ((date == null) ? 0 : date.hashCode());
		result = prime * result + ((from == null) ? 0 : from.hashCode());
		result = prime * result + ((to == null) ? 0 : to.hashCode());
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Message other = (Message) obj;
		if (commandValue == null) {
			if (other.commandValue != null)
				return false;
		} else if (!commandValue.equals(other.commandValue))
			return false;
		if (date == null) {
			if (other.date != null)
				return false;
		} else if (!date.equals(other.date))
			return false;
		if (from == null) {
			if (other.from != null)
				return false;
		} else if (!from.equals(other.from))
			return false;
		if (to == null) {
			if (other.to != null)
				return false;
		} else if (!to.equals(other.to))
			return false;
		if (type == null) {
			if (other.type != null)
				return false;
		} else if (!type.equals(other.type))
			return false;
		return true;
	}
}
